
import os, cgi, time, string
import urllib2, logging, base64
from django.utils import simplejson
from google.appengine.ext import webapp   
from google.appengine.api import users

from google.appengine.ext.webapp import template
 
import gdata.auth
import gdata.service 
from ghealth import *     

from keys import H9_RSA_KEY
from keys import CONSUMER_KEY

     

H9_AUTHSUB_HANDLER = 'https://www.google.com/h9/authsub'
H9_SCOPE = 'https://www.google.com/h9/feeds/'

if os.environ.get('SERVER_SOFTWARE','').startswith('Devel'):
   H9_NEXT_URI = 'http://localhost:8106/authsub'
   AUTHSUB_PARMS = '&secure=0&permission=1&session=1'
else:
   H9_NEXT_URI = 'https://chiefmedicalofficer.appspot.com/authsub'
   AUTHSUB_PARMS = '&permission=1'

class GoogleHealthConnect(object):
   """ Common object to hold connection to Health record 
   """ 
   def __init__(self, client=None):
       #
       if not client:
          client = gdata.health.service.HealthService(source='chiefmedicalofficer-v1', use_h9_sandbox=True) 
          self.key = H9_RSA_KEY 
          # below is for using Oauth rather then AuthSub  need a different key to do this
          #SIG_METHOD = gdata.auth.OAuthSignatureMethod.RSA_SHA1 
          #client.SetOAuthInputParameters(SIG_METHOD, CONSUMER_KEY, rsa_key=self.key)
       self.client = client
       gdata.alt.appengine.run_on_appengine(self.client)  
          
   def revokeProfile(self):
       self.client.RevokeOAuthToken()
       self.client.token_store.remove_all_tokens()
       self.logged_in == False
       
   def getCCR(self, view_vals={}):
       #params = {'digest': 'true', 'strict': 'true'} 
       params = {'strict': 'true'} 
       query = gdata.health.service.HealthProfileQuery(service='h9', params=params)
       #logging.info("ProfileQueryURI is %s"%query.ToUri())
       profile_feed = self.client.GetProfileFeed(query)
       ccrreader = GoogleHealthCCRReader(profile_feed)
       view_vals = view_vals
       view_vals['medications']  = ccrreader.get_medications() 
       view_vals['conditions']   = ccrreader.get_conditions()
       #view_vals['immunizations']= ccrreader.get_immunizations()
       #view_vals['procedures']   = ccrreader.get_procedures()   
       #view_vals['test_results'] = ccrreader.get_test_results()   
       #view_vals['demographics'] = ccrreader.get_demographics()
       return view_vals

   def getTestResults(self, view_vals={}):
       #params = {'digest': 'true', 'strict': 'true'} 
       params = {'strict': 'true'} 
       query = gdata.health.service.HealthProfileQuery(service='h9', params=params)
       #logging.info("ProfileQueryURI is %s"%query.ToUri())
       profile_feed = self.client.GetProfileFeed(query)
       ccrreader = GoogleHealthCCRReader(profile_feed)
       view_vals = view_vals
       view_vals['immunizations']= ccrreader.get_immunizations()
       view_vals['procedures']   = ccrreader.get_procedures()   
       view_vals['test_results'] = ccrreader.get_test_results()   
       return view_vals

   def getProfile(self, view_vals={}):
       #params = {'digest': 'true', 'strict': 'true'} 
       params = {'strict': 'true'} 
       query = gdata.health.service.HealthProfileQuery(service='h9', params=params)
       #logging.info("ProfileQueryURI is %s"%query.ToUri())
       profile_feed = self.client.GetProfileFeed(query)
       ccrreader = GoogleHealthCCRReader(profile_feed)
       view_vals = view_vals
       #view_vals['medications']  = ccrreader.get_medications() 
       #view_vals['conditions']   = ccrreader.get_conditions()
       #view_vals['immunizations']= ccrreader.get_immunizations()
       #view_vals['procedures']   = ccrreader.get_procedures()   
       #view_vals['test_results'] = ccrreader.get_test_results()   
       view_vals['demographics'] = ccrreader.get_demographics()
       return view_vals
       
 

class BaseRequestHandler(webapp.RequestHandler):
  """Base template rendering function.
     The get methods of all classes just need to call the
     render_response() method with template variables.  This base class
     finds teh right template path and adds some other used values
  """  
  _OUTPUT_TYPES = {
    'default': ['text/html', 'html'],
    'html': ['text/html', 'html'], 
    'json': ['application/json', 'json'], 
    'atom': ['application/atom+xml', 'xml'],}
  
  logged_in = False
  
  def template_path(self, filename):
    """Returns the full path for a template from its path relative to here."""
    directory = os.path.dirname(__file__) 
    return os.path.join(directory, os.path.join( 'views', filename))
  
  def render_response(self, filename, template_values={}):
    """Renders a Django template and sends it to the client.
       template_values: argument dict for the template
    """ 
    values ={'current_uri': self.request.uri, 
             'application_name': 'chiefmedicalofficer',
             'login_link': self.get_login_link(),
             'logged_in': self.logged_in,
             'flash': cgi.escape(self.request.get('flash')) }
    values.update(template_values)
    
    output_name = template_values.get("output_format", "default")
    output_type = BaseRequestHandler._OUTPUT_TYPES[output_name] 
    # append .html to template if not provided, emable future xml and other template langs
    if len(filename.split(".")) == 1 :
      filename = '%s.%s' %(filename, output_type[1])      
    path = self.template_path(filename) 
    self.response.headers['Content-Type'] = output_type[0]
    if output_type[0] == "json":
        self.response.out.write(values)
    else:    
        self.response.out.write(template.render(path, values, debug= True))
  
  # Below is the auth token managmenet aspects of the controller 
  def get_authsub_uri(self):
      authsuburi = gdata.service.GenerateAuthSubRequestUrl(
            H9_NEXT_URI, [H9_SCOPE], hd='default', secure=True, session=True, 
            request_url=H9_AUTHSUB_HANDLER, include_scopes_in_next=True)
      authsuburi += AUTHSUB_PARMS
      return authsuburi  
  
  def get_view_defaults(self):
      view_vals = {'health_info': '', 'msg': ''}
      return view_vals
      
  def get_token_or_show_login(self): 
      # do not use just a failed experiment
      user = users.get_current_user() 
      self.client = gdata.health.service.HealthService(source='chiefmedicalofficer-v1', use_h9_sandbox=True)   
      gdata.alt.appengine.run_on_appengine(self.client)
      view_vals = {'health_info': '', 'msg': ''} 
      # Attempt to get stored token
      token = self.client.GetAuthSubToken()
      if token and isinstance(token, gdata.auth.AuthSubToken):
          logging.info(token)
          self.logged_in = True 
          if False:
              authsuburi = self.get_authsub_uri()
              self.redirect('index_public', {'login_url': authsuburi, 'username':user.nickname()}) 
      else:
          # Attempt to extract an AuthSub token from the current URI
          token = gdata.auth.extract_auth_sub_token_from_url(self.request.uri, rsa_key=H9_RSA_KEY)
          if token:
              self.client.UpgradeToSessionToken(token)
              token = self.client.GetAuthSubToken() 
              headers = {'Authorization': 'AuthSub token="'+token+'"'}
              self.client = gdata.health.service.HealthService(source='chiefmedicalofficer-v1', 
                                                               use_h9_sandbox=True,
                                                               additional_headers=headers)                   
              self.logged_in = True 
          else:
              authsuburi = self.get_authsub_uri()
              self.render_response('index_public', {'login_url': authsuburi, 'username':user.nickname()}) 
          
          # below is just for debug and can be removed in production
          view_vals['single_token'] = str(token)
          #view_vals['auth_token'] = self.client.AuthSubTokenInfo()  
          view_vals['session_token'] = self.client.GetAuthSubToken()
      return view_vals
  
  def get_login_link(self):
      if self.logged_in == True:
          return '<a href="/logout">logout</a>' 
      return '<a href="'+self.get_authsub_uri()+'" >login</a>'
      
  def clear_session(self):
      self.client.RevokeAuthSubToken()
  
  def get_cookie(key_name, default=''):
      """ This will return the value of the cookie with key_name"""
      return self.request.cookies.get(key_name, default)

  def set_cookie(key_name, value=''):
      """ This will set the value of the cookie with key_name""" 
      expire_date = time.time() + 60 * 60 * 24 * 7 * 2 # expire in two weeks
      self.response.headers.add_header('Set-Cookie','%s=%s; expires=' %(key_name, value.encode(), expire_date))

  def error_page(self, error, msg=''):
     self.render_response('error.html',{'error': error,'msg': msg})  


